package org.cerberus.platform.ograph;

import java.util.HashMap;
import java.util.Map;

public final class ComponentClass {

	private final String className;
	private final String classID;
	private final boolean defaultVisible;
	private final boolean modal;
	private final ComponentClass superClass;
	
	//TODO implement these fully
	private ComponentClassResource[] resources;
	private ComponentClassEvent[] events;
	
	private ComponentClassAttribute[] attributes;
	private Map<String, ComponentClassAttribute> attributeMap;
	private ComponentClassAttribute[] resolvedAttributes;
	
	private int attributeCount;
	
	ComponentClass(ComponentClass superClass, 
			String className, 
			String classID,
			boolean defaultVisible,
			boolean modal) {
		this.superClass = superClass;
		this.defaultVisible = defaultVisible;
		this.modal = modal;
		this.className = className;
		this.classID = classID;
	}
	
	public ComponentClassAttribute getAttribute(String attributeName) {
		if (attributeMap == null) {
			return null;
		}
		ComponentClassAttribute attribute = attributeMap.get(attributeName);
		if (attribute == null && superClass != null) {
			return superClass.getAttribute(attributeName);
		}
		return attribute;
	}
	
	public ComponentClassAttribute[] getAttributes() {
		if (resolvedAttributes != null) {
			return resolvedAttributes;
		}
		ComponentClassAttribute[] superAttributes = superClass != null ? superClass.getAttributes() : null;
		if (attributes == null && superAttributes == null) {
			resolvedAttributes = new ComponentClassAttribute[0];
		} else if (superAttributes == null) {
			resolvedAttributes = attributes;
		} else if (attributes == null) {
			resolvedAttributes = superAttributes;
		} else {
			resolvedAttributes = new ComponentClassAttribute[resolvedAttributes.length + attributes.length];
			System.arraycopy(superAttributes, 0, resolvedAttributes, 0, superAttributes.length);
			System.arraycopy(attributes, 0, resolvedAttributes, superAttributes.length, superAttributes.length);
		}
		return resolvedAttributes;
	}
	
	void defineAttributes(ComponentClassAttribute[] attributes) {
		if (this.attributes != null) {
			throw new ComponentClassException("Attributes already defined.");
		}
		if (attributes != null && attributes.length > 0) {
			this.attributes = attributes;
			this.attributeMap = new HashMap<String, ComponentClassAttribute>(attributes.length);
			for (int i = 0; i < attributes.length; i++) {
				attributes[i].defineIndex(i, superClass != null ? superClass.getDeclaredAttributeCount()+i : i);
				attributeMap.put(attributes[i].getName(),  attributes[i]);
			}
			attributeCount = attributes.length;
		}
	}
	
	void defineEvents(ComponentClassEvent[] events) {
		this.events = events;
	}
	
	void defineResources(ComponentClassResource[] resources) {
		this.resources = resources;
	}
	
	public ComponentClassResource[] getDeclaredResources() {
		return resources;
	}
	public ComponentClassAttribute[] getDeclaredAttributes() {
		return attributes;
	}
	public ComponentClassEvent[] getDeclaredEvent() {
		return events;
	}
	
	public int getDeclaredAttributeCount() {
		return attributeCount;
	}
	
	public int getAttributeCount() {
		if (superClass != null) {
			return superClass.getAttributeCount() + attributeCount;
		}
		return attributeCount;
	}
	
	public boolean hasResources() {
		return resources != null ? true : superClass != null ?  superClass.hasResources() : false;
	}
	
	public boolean hasEvents() {
		return events != null ? true : superClass != null ? superClass.hasEvents() : false;
	}
	
	public boolean hasAttributes() {
		return attributes != null ? true : superClass != null ? superClass.hasAttributes() : false;
	}

	public String getClassName() {
		return className;
	}
	public String getClassID() {
		return classID;
	}
	public boolean isDefaultVisible() {
		return defaultVisible;
	}
	public boolean isModal() {
		return modal;
	}

	public ComponentClass getSuperClass() {
		return superClass;
	}
	
}
